#-------------------------------------------------------------------------------
# Name:        Main
# Purpose:
#
# Author:      Pablo
#
# Created:     11/02/2012
# Copyright:   (c) Monxcleyr Productions 2012
# Licence:     GPL v3
#-------------------------------------------------------------------------------
#!/usr/bin/env python

import pygame, sys, os, webbrowser, logging
import game, title, config, options
import time as pytime
from ..tools import videotools, versioncheck, news
from pygame.locals import *

def main():

  logging.info('Initializing Engine')
  logging.info("Arguments: %s", sys.argv)
  logging.info('Pygame version %s' % pygame.ver)

#--------------------------- Main Window Inits ---------------------------------


  if sys.platform == 'win32' or sys.platform == 'win64':
    os.environ['SDL_VIDEO_CENTERED'] = '1' #Center screen on windows
    os.environ['SDL_VIDEODRIVER'] = 'windib' #Use better video thing on windows

  fpsClock = pygame.time.Clock()
  fps = 0
  meanfps = []
  averagefps = 0
  highestfps = 0
  runtime = 0
  time = 0
  screenshot = False
  poll = 0

#-------------------------------------------------------------------------------

  # Pre-init mixer for sounds. I guess some OSes require this, even though we are going to
  # quit the mizer and then reinitialize after the intro video anyways.
  pygame.mixer.pre_init(frequency=22050, size=-16, channels=2, buffer=1024)
  pygame.init()
##  pygame.key.set_repeat(100,50) # Keys repeat

  #Initialize game
  g = game.Game()

  pygame.display.set_caption(g.common.caption)
##  g.screen.set_colorkey((255,0,255))

  time = 0
  running = True # Controls the main loop
  mouse = [(-50,-50), 0, 0, 0, 0, 0, 0]
  consolemouse = [(-50,-50), 0, 0, 0, 0, 0, 0]

#--------------------- Process Commandline Arguments --------------------------

  nologo = False
  debug = False
  nofps = False
  editor = False
  fpscap = 70
  titlefps = False
  debuglite = False
  balloonmode = False
  console = False

  if len(sys.argv) > 1:
    g.debug.setArgv(sys.argv[1:])
    for argv in sys.argv:
      if argv == '-nologo':
        nologo = True
      elif argv == '-debug':
        debug = True
        g.debug.setEnabled(True)
      elif argv == '-nofps':
        nofps = True
      elif argv == '-editor':
        editor = True
      elif argv == '-fps':
        titlefps = True
      elif argv == '-debuglite':
        debuglite = True
      elif argv == '-console':
        console = True
      elif argv.startswith('-fpscap:'):
        fpscap = float(argv[8:])
        if fpscap > 200:
          fpscap = 200
        g.common.fps = fpscap
      elif argv.startswith('-mode:'):
        g.setMode(int(argv[6:]))
      elif argv == '-exception':
        raise RuntimeError('-exception commandline argument used.')
      elif argv == '-99':
        balloonmode = True

      g.debugstates = (debug, debuglite, console)

#---------------------------- Splash Screen ------------------------------------

  if nologo == False:
    pygame.mouse.set_visible(False)
    splashrunning = True
    splash = title.ImageTitle(g.titleS)

    while splashrunning == True:
      # Keep the window the same scale
      for event in pygame.event.get():
        if event.type == QUIT:
          splashrunning = False
          running = False
        elif event.type == KEYDOWN:
          if event.key == K_ESCAPE:
            splashrunning = False

      temp = splash.draw(0)
      if temp == 0:
        running = False
        splashrunning = False
      elif temp == 1:
        splashrunning = False

      # Update the screen
      titletemp = pygame.Surface(g.size)
      pygame.transform.smoothscale(g.titleS, g.size, titletemp)
      g.screen.blit(titletemp, (0,0))
      pygame.display.flip()
      fpsClock.tick(30)

  # Reset sound mixer and initialize the engine sounds if we are not quitting the game.
  if running == True:
    pygame.mixer.quit()
    pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=g.common.buffersize)
    pygame.display.set_caption(g.common.caption + ': Loading...')
    g.postInit()
    pygame.display.set_caption(g.common.caption)
    # Awww, we get a cute mouse again :D
    pygame.mouse.set_visible(True)


#-------------------------------------------------------------------------------
#------------------------------ Version Check ----------------------------------
#-------------------------------------------------------------------------------

  checkversion = versioncheck.VersionCheck()
  checkversion.check(g.common.name, g.common.version)

  # Create dialog if there is a new version avaliable
  if not checkversion.info['up-to-date']:
    text = "Version " + str(checkversion.info['updateversion']) + " available! \nDownload at " + str(checkversion.info['link'])
    g.dialog.addDialog('versioncheck', text, (3,515), [0], 'versioncheck')

##  g.dialog.addDialog('notification', ' ', (798,222), [0], 'news')
##  g.dialog.getDialogByName('news').loadText('changes.txt')


#-------------------------------------------------------------------------------
#---------------------------------- NEWS ---------------------------------------
#-------------------------------------------------------------------------------

  newsenabled = True
  if newsenabled:
    checknews = news.News()

    newstext = checknews.check(g.common.name)
    if newstext != None:
      g.dialog.addDialog('notification', ' ', (798,222), [0], 'news')
      g.dialog.getDialogByName('news').text = newstext

#-------------------------------------------------------------------------------
#-------------------------------- MAIN LOOP ------------------------------------
#-------------------------------------------------------------------------------


  while running == True:
    # Reset mouse variable
    mouse = [mouse[0], 0, 0, 0, 0, 0, 0]
    consolemouse = [consolemouse[0], 0, 0, 0, 0, 0, 0]
    keyDict = {}
    g.common.keyState.reset()
    g.common.keyState.poll()

    # Main event loop will only handle the mouse. This is due to pygame event being weird
    # when being called twice. So anything that needs the mouse will have the mouse list
    # passed in as an argument. Classes that require keypresses will handle those themselves
    # using pygame.key.get_pressed()[index] and passing g.key.bind to get the user-defined
    # keyboard controls

##    if pygame.mouse.get_focused() == 0:
##      mouse[0] = (-50,-50)
    if True not in g.debugstates:
      g.console.active = False
    g.console.process_input()
    for event in pygame.event.get():
      if event.type == QUIT or g.checkQuit() == True:
        pygame.quit()
        sys.exit()
      # Mouse -----
      if event.type == MOUSEMOTION:
        mouse[0] = g.common.videomouse.scale(event.pos, g.size)
        consolemouse[0] = event.pos
      if event.type == MOUSEBUTTONDOWN:
        mouse[event.button] = 1
        consolemouse[event.button] = 1
      if event.type == MOUSEBUTTONUP:
        mouse[event.button] = 2
        consolemouse[event.button] = 2

      if event.type == KEYDOWN:
        g.common.keyState.setKeydown(event.key)

        if event.key == g.common.key.bind['screenshot']:
          datetime = pytime.strftime('%m-%d-%Y_%H.%M.%S')
          screenshot = True
        if event.key in range(256):
          if chr(event.key) == "`" and True in g.debugstates:
            g.console.set_active()


      if event.type == KEYUP:
        g.common.keyState.setKeyup(event.key)

#-------------------------------------------------------------------------------


    # Scale the preS surface immediately after checking if the window size has changed.
    g.preS = pygame.Surface(g.size)
##    g.screen.fill((255,255,255))


#-------------------------------------------------------------------------------
#----------------------------------- MODES -------------------------------------
#-------------------------------------------------------------------------------

    # Here the engine checks what mode the engine is in, and executes the appropriate code.
    # The lost of modes can be found in game.py


    # ---- Main Menu ----
    if g.mode == 0:

      # remove world instance from game
      if hasattr(g, 'world'):
        del g.world

      # Drawing menu surface. This will get moved to bottom of menu section later, I think.
      g.options.firstdraw = True
      g.savescreen.firstdraw = True
      menutemp = ''
      if balloonmode:
        menutemp = g.menu.draw(mouse, g.starfield, True)
      else:
        menutemp = g.menu.draw(mouse, g.starfield)

      # Draw Dialog Boxes
      g.dialog.draw(menutemp, mouse, g.sound, g.common, g.mode)
      # Draw version
      checkversion.draw(menutemp, (3, 564))

      if g.menu.cursor != None:
        menutemp.blit(g.menu.cursor, mouse[0])

      if g.common.settings.quality == 1:
        pygame.transform.scale(menutemp, g.size, g.preS)
      else:
        pygame.transform.smoothscale(menutemp, g.size, g.preS)

      # Debug testing here.
      if debug == True:
        pass

      # Menu buttons.
      if g.menu.getSelected() == (0,0):
        pass
      else:
        state = g.menu.getSelected()
        g.debug.add('Button: ' + str(state[0]) + ' Mode: ' + str(state[1]))
        mode = state[1]
        if mode == 'QUIT':
          g.quit = 1
        elif mode == 'LINK':
          webbrowser.open_new_tab(g.menu.menu_item[state[0] - 1].link)
          g.debug.add('Opening ' + str(g.menu.menu_item[state[0] - 1].link))
        else:
          g.setMode(int(state[1]))

    # ---- Options Menu ----
    if g.mode == 4:

      # reset main menu
      g.menu.reset()

      if g.options.getSelected() == (0,0):
        pass
      else:
        state = g.options.getSelected()
        g.debug.add('Button: ' + str(state[0]) + ' Mode: ' + str(state[1]))
        mode = state[1]
        if mode == 'QUIT':
          g.options.quit()
          g.usePrevMode()
          # Settings don't reset correctly, so we just reinit the options class after
          # reloading g.common.settings with g.options.quit()
          g.options = options.Options(g.optionS, 'options.ini', g.common, g.sound, g.music, g.debug, g.size)
        elif mode == 'SAVE':
          g.options.save()
          g.usePrevMode()
          g.size = (g.common.reswidths[g.common.settings.res_setting], g.size[1])
          g.size = g.common.videoresize.scale(g.common.scale, g.size) # Get new size
          g.preS = pygame.Surface(g.size)
          if g.common.settings.fullscreen == True:
            pygame.display.set_mode(g.size, SRCALPHA|DOUBLEBUF|FULLSCREEN|HWSURFACE)
          else:
            pygame.display.set_mode(g.size, SRCALPHA|DOUBLEBUF|HWSURFACE)
        elif mode == 'DEFAULT':
          g.options.defaults()


      # Draw options menu
      optionstemp = g.options.draw(mouse, g.prevmode, g.starfield)
      if g.common.settings.quality == 1:
        pygame.transform.scale(optionstemp, g.size, g.preS)
      else:
        pygame.transform.smoothscale(optionstemp, g.size, g.preS)


    # ---- Game Mode ----
    if g.mode == 1:
      g.runGame(int(fpsClock.get_time()), mouse)
      if g.common.settings.quality == 1:
        pygame.transform.scale(g.gameS, g.size, g.preS)
      else:
        pygame.transform.smoothscale(g.gameS, g.size, g.preS)
##      g.updatePreS(g.gameS)

    # ---- New Game ----
    if g.mode == 2:
      g.menu.reset()

      if g.savescreen.firstdraw:
        g.savescreen.mode = 'new'

      for widget in g.savescreen.widgets:
        if widget.selected:
          g.savescreen.selected = widget.save
          if widget.hasfile:
            g.savescreen.mode = 'newoverwrite'
          else:
            g.savescreen.mode = 'namedialog'


      surf = g.savescreen.draw(mouse, g.starfield)
      g.updatePreS(surf)

      if g.savescreen.savename is not '':
        g.newGame(g.savescreen.savename, g.savescreen.selected)
        g.savescreen.reset()


      # Buttons
      if g.savescreen.getSelected() == (0,0):
        pass
      else:
        state = g.savescreen.getSelected()
        g.debug.add('Button: ' + str(state[0]) + ' Mode: ' + str(state[1]))
        mode = state[1]
        if mode == 'CANCEL':
          g.usePrevMode()
          g.savescreen.reset()
        else:
          g.setMode(int(state[1]))

    # ---- Load Game ----
    if g.mode == 3:
      g.menu.reset()
      g.savescreen.mode = 'load'
      surf = g.savescreen.draw(mouse, g.starfield)
      g.updatePreS(surf)

      # Buttons
      if g.savescreen.getSelected() == (0,0):
        pass
      else:
        state = g.savescreen.getSelected()
        g.debug.add('Button: ' + str(state[0]) + ' Mode: ' + str(state[1]))
        mode = state[1]
        if mode == 'CANCEL':
          g.usePrevMode()
          g.savescreen.reset()
        else:
          g.setMode(int(state[1]))

      for widget in g.savescreen.widgets:
        if widget.selected:
          g.loadSave(str(widget.save))
          g.savescreen.reset()


    # ---- Mini Game ----
    if g.mode == 11:
      g.minigame.run(g.world)
      g.mode = 1

    # ---- Pause Screen ----
    if g.mode == 5:
      g.savescreen.firstdraw = True

      if g.pause.dialog is False:
        surf, temp = g.pause.draw(g.gameS, mouse)
        # Return to game if they hit the unpuase button
        if temp == 1:
          g.setMode(temp)
        g.updatePreS(surf)
        if g.mode != 5:
          # replace this later with having the game mode recheck if cursor should be drawn, etc
          pygame.mouse.set_visible(False)
          g.pause.count = 0

      # Buttons

      if not g.pause.dialog or not g.pause.firstdraw and not g.pause.canceled:
        if g.pause.getSelected() == (0,0):
          pass
        else:
          state = g.pause.getSelected()
          g.debug.add('Button: ' + str(state[0]) + ' Mode: ' + str(state[1]))
          mode = state[1]
          if mode == 'QUIT':
            g.quit = 1
          elif mode == 'LINK':
            webbrowser.open_new_tab(g.pause.menu_item[state[0] - 1].link)
            g.debug.add('Opening ' + str(g.pause.menu_item[state[0] - 1].link))
          elif mode == 'SAVE':
            g.saveWorld('1')
          elif mode == 'MENU':
            g.pause.dialog = True
            g.pause.firstdraw = True
          else:
            g.setMode(int(state[1]))

      # If the dialog box is running, draw stuff after the button checks. This was a huge
      # pain to fix. Not doing so makes menu slections happen when clicking cancel. :/
      if g.pause.dialog:
        surf, temp = g.pause.draw(g.gameS, mouse)
        # Return to game if they hit the unpuase button
        if temp == 1:
          g.setMode(temp)
        g.updatePreS(surf)
        if g.mode != 5:
          # replace this later with having the game mode recheck if cursor should be drawn, etc
          pygame.mouse.set_visible(False)
          g.pause.count = 0


      if g.pause.mode == False:
        g.setMode(0)
        g.pause.reset()

    # Returns engine to previously used mode
    if g.mode == 8:
      g.usePrevMode()


    # ---- Credits Screen ----
    if g.mode == 9:

      surf = g.credits.draw(g.starfield, pygame.time.get_ticks(), int(fpsClock.get_time()))
      if g.common.settings.quality == 1:
        pygame.transform.scale(surf, g.size, g.preS)
      else:
        pygame.transform.smoothscale(surf, g.size, g.preS)

      if not g.credits.running:
        g.credits.reset()
        g.mode = 0



    # ---- Save Screen ----
    if g.mode == 10:

      if g.savescreen.firstdraw:
        g.savescreen.mode = 'save'

      for widget in g.savescreen.widgets:
        if widget.selected:
          g.savescreen.selected = widget.save
          if widget.hasfile and g.savescreen.mode is not 'saveslot':
            g.savescreen.mode = 'saveoverwrite'
          elif g.savescreen.mode is not 'saveslot':
            g.savescreen.mode = 'saveslot'


      surf = g.savescreen.draw(mouse, g.starfield, g.gameS)
      g.updatePreS(surf)

      if g.savescreen.mode is 'saveslot':
        g.saveWorld(str(g.savescreen.selected))
        g.mode = 8
        g.savescreen.reset()

      # Buttons
      if g.savescreen.getSelected() == (0,0):
        pass
      else:
        state = g.savescreen.getSelected()
        g.debug.add('Button: ' + str(state[0]) + ' Mode: ' + str(state[1]))
        mode = state[1]
        if mode == 'CANCEL':
          g.usePrevMode()
          g.savescreen.reset()
        else:
          g.setMode(int(state[1]))




#-------------------------------- Debug Stuff ----------------------------------

    fps = int(fpsClock.get_fps())
    if debug == True:
      time = int(fpsClock.get_time())
##      print pygame.time.get_ticks()
      runtime = int(pygame.time.get_ticks() / 1000)

      meanfps.append(fps)
      if len(meanfps) >= 100:
        meanfps.pop(0)
      temp = 0
      for i in meanfps:
        temp += i
      averagefps = temp / len(meanfps)

      # Update debug
      g.debug.resetWidth(g.preS.get_width())

#--------------------- Update Screen and end of loop ---------------------------

    # Draw the final screen
    if hasattr(g, 'world'):
      gametime = g.world.gametime
    else:
      gametime = 0
    g.debug.draw(g.preS, fps, averagefps, runtime, time, gametime, g.mode, g.modes)
    g.console.parent_screen = g.preS
    g.console.draw(consolemouse)
    g.screen.blit(g.preS, (0,0))
    if g.mode == 1:
##      pass
      pygame.display.flip()
##      pygame.display.update(g.getDirtyRects())
    else:
      pygame.display.flip()


    # Keep starfield speed in sync with fps
    if int(fpsClock.get_time()) <= 60:
      g.starfield.setFrameRate(int(fpsClock.get_time()))


    # Take a screenshot AWWWYEAH
    if screenshot == True and g.options.drawcursor:
      pygame.image.save(g.screen, os.path.join('Screenshots/', datetime + '.png'))
      g.debug.add('Screenshot saved')
      screenshot = False

    # Draw fps in titlebar if enabled:
    if titlefps == True:
      pygame.display.set_caption(g.common.caption + ' | FPS: ' + str(fps))

    # Debuglite mode
    if debuglite == True:
      pygame.display.set_caption(g.common.caption + ' | FPS: ' + str(fps) + ' || ' + g.debug.argv)


    # FPS handling
    if nofps == True:
      fpsClock.tick(200)
    else:
      fpsClock.tick(g.common.fps)
    poll = 0

  # So Pyscripter can quit
  pygame.quit()

if __name__ == '__main__':
  main()
